package service

import (
	"context"
	"fx_swift_ifcgate/api"
	"fx_swift_ifcgate/internal/model"
	"fx_swift_ifcgate/pkg/code"
	"fx_swift_ifcgate/pkg/global"
	"fx_swift_ifcgate/pkg/internalerrors"
	"fx_swift_ifcgate/pkg/logger"
	"fx_swift_ifcgate/pkg/page"
	"fx_swift_ifcgate/pkg/utils"
	"github.com/gogf/gf/v2/container/gvar"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/golang-module/carbon/v2"
	"github.com/spf13/cast"
)

// 换汇
type IExchangeCurrencySrv interface {
	// 查询实时汇率
	OttPayTp1002(ctx context.Context, req *api.Tp1002Req) (*api.Tp1002ApiRes, error)
	// 查询当前商户号对应的钱包
	OttPayTp3004(ctx context.Context) (*api.Tp3004Res, error)
	// 换汇
	OttPayTp1003(ctx context.Context, quoteId string) error
	// 换汇明细列表
	ExchangeCurrencyList(ctx context.Context, req *api.ExchangeCurrencyListReq) (*page.Collection[*api.ExchangeCurrencyListRes], error)
}
type exchangeCurrencySrv struct {
}

func NewExchangeCurrencySrv() IExchangeCurrencySrv {
	return &exchangeCurrencySrv{}
}

// 查询实时汇率
func (e *exchangeCurrencySrv) OttPayTp1002(ctx context.Context, req *api.Tp1002Req) (*api.Tp1002ApiRes, error) {
	var (
		err           error
		tp1002Res     *api.Tp1002Res
		merchantNo    string
		merchantToken string
		redisResult   *gvar.Var
	)
	merchantNo = ctx.Value("MerchantNo").(string)
	redisResult, err = g.Redis().Get(ctx, merchantNo)
	if err != nil || redisResult.IsEmpty() {
		return &api.Tp1002ApiRes{}, internalerrors.New(code.ErrUnknown, "获取商户号对应的token失败")
	}
	merchantToken = redisResult.String()

	if req.BuyCurrency == req.SellCurrency {
		tp1002ApiRes := &api.Tp1002ApiRes{}
		tp1002ApiRes.Body.Rate = "1"
		tp1002ApiRes.Body.MerOrderNo = ""
		tp1002ApiRes.Body.QuoteId = ""
		tp1002ApiRes.Body.BuyCurrency = req.BuyCurrency
		tp1002ApiRes.Body.BuyAmount = req.Amount
		tp1002ApiRes.Body.SellAmount = ""
		tp1002ApiRes.Body.SellCurrency = req.SellCurrency
		tp1002ApiRes.Body.ExpireTime = carbon.Now().TimestampMilli()
		return tp1002ApiRes, err
	}
	req.MerOrderNo = utils.GenerateCode32()
	tp1002Res, err = PostTp1002(req, merchantToken)
	if err == nil && tp1002Res != nil {
		tp1002ApiRes := &api.Tp1002ApiRes{}
		tp1002ApiRes.Body.Rate = tp1002Res.Body.Rate
		tp1002ApiRes.Body.MerOrderNo = tp1002Res.Body.MerOrderNo
		tp1002ApiRes.Body.QuoteId = cast.ToString(tp1002Res.Body.QuoteId)
		tp1002ApiRes.Body.BuyCurrency = tp1002Res.Body.BuyCurrency
		tp1002ApiRes.Body.BuyAmount = tp1002Res.Body.BuyAmount
		tp1002ApiRes.Body.SellAmount = tp1002Res.Body.SellAmount
		tp1002ApiRes.Body.SellCurrency = tp1002Res.Body.SellCurrency
		tp1002ApiRes.Body.ExpireTime = tp1002Res.Body.ExpireTime
		return tp1002ApiRes, err
	}
	return nil, err
}

// 查询当前商户号对应的钱包
func (e *exchangeCurrencySrv) OttPayTp3004(ctx context.Context) (*api.Tp3004Res, error) {
	var (
		err           error
		merchantToken string
		tp13004Res    *api.Tp3004Res
	)
	merchantToken, err = GetMerchantToToken(ctx)
	if merchantToken == "" || err != nil {
		logger.SugarLogger.Error(err)
		return nil, internalerrors.New(code.ErrUnknown, err.Error())
	}
	tp13004Res, err = PostTp3004(&api.Tp3004Req{}, merchantToken)
	if err == nil && tp13004Res != nil {
		return tp13004Res, err
	}
	return nil, err
}

// 换汇
func (e *exchangeCurrencySrv) OttPayTp1003(ctx context.Context, quoteId string) error {
	var (
		err           error
		merchantNo    string
		tp1003Res     *api.Tp1003Res
		merchantToken string
		account       string
		feeStatus     string
	)

	merchantNo = ctx.Value("MerchantNo").(string)

	feeStatus = ctx.Value("FeeStatus").(string)
	if feeStatus != "1" {
		return internalerrors.New(code.ErrEmptyData, "手续费为配置,无法交易")
	}

	merchantToken, err = GetMerchantToToken(ctx)
	if err != nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, err.Error())
	}

	account, err = GetAccountToMerchantNo(ctx)
	if err != nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, err.Error())
	}

	tp1003Res, err = PostTp1003(&api.Tp1003Req{
		QuoteId:     quoteId,
		CallbackUrl: global.ViperObj.GetString("callback.tp1003"),
	}, merchantToken)
	if err != nil || tp1003Res == nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	if _, err = global.GFDB.Insert(ctx, "ifcgate_exchange_currency", &model.IfcgateExchangeCurrency{
		MerchantNo:   merchantNo,
		Account:      account,
		SellCurrency: tp1003Res.Body.SellCurrency,
		BuyCurrency:  tp1003Res.Body.BuyCurrency,
		Rate:         tp1003Res.Body.Rate,
		SellAmount:   tp1003Res.Body.SellAmount,
		BuyAmount:    tp1003Res.Body.BuyAmount,
		QuoteId:      tp1003Res.Body.QuoteId,
		BizFlow:      tp1003Res.Body.BizFlow,
		Status:       "INIT",
		Msg:          "",
	}); err != nil {
		logger.SugarLogger.Error(err)
		return internalerrors.New(code.ErrUnknown, err.Error())
	}
	return err
}

// 换汇明细列表
func (e *exchangeCurrencySrv) ExchangeCurrencyList(ctx context.Context, req *api.ExchangeCurrencyListReq) (*page.Collection[*api.ExchangeCurrencyListRes], error) {
	var (
		err        error
		total      int
		merchantNo string
		resultList []*api.ExchangeCurrencyListRes
	)

	collectionDto := &page.Collection[*api.ExchangeCurrencyListRes]{}
	collectionDto.Page = uint64(req.PageNo)
	collectionDto.PageSize = uint64(req.PageSize)

	merchantNo = ctx.Value("MerchantNo").(string)
	if len(merchantNo) > 0 {
		mod := global.GFDB.Ctx(ctx).Model("ifcgate_exchange_currency")
		if len(req.Currency) > 0 {
			mod.WhereLike("buy_currency", "%"+req.Currency+"%")
		}
		if len(req.BizFlow) > 0 {
			mod.WhereLike("biz_flow", "%"+req.BizFlow+"%")
		}
		if len(req.Status) > 0 {
			mod.Where("status=?", req.Status)
		}
		if len(req.StartTime) > 0 && len(req.EndTime) > 0 {
			mod.Where("created_at >=? and created_at <=?", req.StartTime+" 00:00:00", req.EndTime+" 23:59:59")
		}
		mod.Where("merchant_no=?", merchantNo)
		mod.Order("created_at desc")
		mod.Limit(int(page.PageToOffset(uint64(req.PageNo), uint64(req.PageSize))), cast.ToInt(req.PageSize))
		err = mod.ScanAndCount(&resultList, &total, false)
		collectionDto.TotalPage = page.GetTotalPage(uint64(req.PageNo), uint64(req.PageSize), cast.ToInt64(total))
		if err != nil {
			return nil, internalerrors.New(code.ErrUnknown, "数据查询异常")
		}
		collectionDto.Total = cast.ToInt64(total)
		collectionDto.List = resultList
	}
	return collectionDto, err
}
